
#(var fdata (file/open (1 *args*) :r)) #might not be correct? always "args" as ascii tuple...
#(var fdata (:read fdata :all))
(def version "git-0-0-5") #TODO: Get version from project.janet.
(var keyword-macros @{
'+ 'add
'- 'sub
'movbyte (symbol "mov byte")
'= 'mov
})
(defn match-k-macros (lllm-opcode)
 (or (keyword-macros lllm-opcode) (symbol lllm-opcode) )) #warning: not assuming ","

(defn translate (LINE)
 (var INSTR (buffer (match-k-macros (0 LINE))"\t\t"))
 (loop [KYW :in (tuple/slice LINE 1) ]
  (buffer/push-string INSTR (string (match-k-macros KYW) ",\t")))
 (var INSTR (buffer/slice INSTR 0 -3)) # remove ",\t".
 INSTR)

(defn translates (PROGRAM-DATA)
 (var COMPILED (buffer "\n;;;;\t[Low Level Lisp MetAssembler] \n;;;;\t version: lllm-\t" version "\n\n"))
 (loop [LINE :in PROGRAM-DATA]
  (buffer/push-string COMPILED (translate LINE) "\n"))
 COMPILED)

#
##OPTIMIZING
#

### All optimizations under this section are meant to be naive x64-dependent opts.
### This is because optimization is left in large part to the programmer.
(comment
(def opcode-cache @{

                     } )
(defn opcode-cache? (op)
  (or (opcode-cache op)
      false))
(var x64gpr-cache @{:rax 0 :rcx 0 :rdx 0 :rbx 0
                    :rsp 0 :rbp 0 :rsi 0 :rdi 0
                    :r8  0 :r9  0 :r10 0 :r11 0
                    :r12 0 :r13 0 :r14 0 :r15 0})
(defn x64gpr-cacher ([op register & mvalues])
                     (put x64gpr-cache (keyword register) () )) )
(defn optimize (lllm-instr)
  (var lllm-instr lllm-instr) #Mutable, defined in-scope.
  (var lllm-op (match-k-macros (0 lllm-instr) ))
  ##(pp lllm-instr) #Debug.
  (cond (and (=    lllm-op     'mov)
             (= (2 lllm-instr) 0   ))
        (set lllm-instr ~[xor
                          ,(1 lllm-instr)
                          ,(1 lllm-instr)])
        #nil
        #(opcode-cache? lllm-op)
        #    (x64gpr-cacher lllm-op)
            )
  lllm-instr)

(defn optimizes (PROGRAM-DATA)
  (map optimize PROGRAM-DATA ))

#-IMPERATIVE-
(defn lllm (program-buffer)
  (translates (optimizes program-buffer)) )
#(var fdata (:read stdin :all))
#(var fdata (eval-string fdata)) #it's safe. source: trust me
#(print (translates (optimizes fdata)))
